package com.bifrost.service.impl;

import com.bifrost.cbentity.SapContract;
import com.bifrost.cbentity.SapContractProduct;
import com.bifrost.cbentity.SapStoreProduct;
import com.bifrost.cbrepository.SapContractProductRepository;
import com.bifrost.cbrepository.SapContractRepository;
import com.bifrost.cbrepository.SapStoreProductRepository;
import com.bifrost.constant.OrderType;
import com.bifrost.entity.*;
import com.bifrost.exception.SapReportException;
import com.bifrost.exception.SapSendException;
import com.bifrost.model.ResultModel;
import com.bifrost.model.sap.*;
import com.bifrost.model.sap.Payment;
import com.bifrost.model.vo.TransactionVO;
import com.bifrost.repository.*;
import com.bifrost.service.OrderService;
import com.bifrost.service.TransactionService;
import com.bifrost.task.BaseSendTask;
import com.bifrost.task.ReceiptSendTask;
import com.bifrost.task.ReportSendTask;
import com.bifrost.util.DateTimeUtil;
import com.bifrost.util.DateUtils;
import com.bifrost.util.LocalDateUtils;
import com.bifrost.util.XmlUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.CompactWriter;
import com.thoughtworks.xstream.io.xml.DomDriver;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Author by yanxiaobo
 * Date on 2018/5/21$.
 */
@Service("transactionSendService")
public class TransactionServiceImpl implements TransactionService {
    Logger logger = LoggerFactory.getLogger(TransactionService.class);

    public static final int PAGE_SIZE = 50;//分页查询时一次性查询多少条
    private static final long LOCKED_TIME=60*5;

    @Autowired
    TransactionSendLogRepository transactionSendLogRepository;
    @Autowired
    OrderReturnRepository orderReturnRepository;
    @Autowired
    OrderRepository orderRepository;
    @Autowired
    OrderAttributeRepository orderAttributeRepository;
    @Autowired
    SapStoreGoodsRepository sapStoreGoodsRepository;
    @Autowired
    SapContractProductRepository sapContractProductRepository;
    @Autowired
    SapContractRepository sapContractRepository;
    @Autowired
    OrderReturnItemRepository orderReturnItemRepository;
    @Autowired
    OrderItemRepository orderItemRepository;
    @Autowired
    RedissonClient redisson;
    @Autowired
    SapStoreProductRepository sapStoreProductRepository;
    @Autowired
    OrderService orderService;

    @Override
    public void sendReceipt(ReceiptSendTask.Uploader uploader) {
        RLock lock = redisson.getLock(TransactionSendLog.LOCK_KEY.concat("."+uploader.getParam()));
        try{
            boolean locked =  lock.tryLock(LOCKED_TIME, TimeUnit.SECONDS);
            if(locked){
                List<TransactionSendLog> errorList = new ArrayList<>();
                List<TransactionSendLog> logs;
                //获取全部未发送的日志
                switch (uploader.getParam().trim()){
                    // 发送富基小票
                    case "richBaseReceipt":
                        logs = transactionSendLogRepository.findByRichBaseReceipt(false, new PageRequest(0, PAGE_SIZE));
                        break;
                    // 发送Sap小票
                    case "sapReceipt":
                        logs = transactionSendLogRepository.findBySuccess(false, new PageRequest(0, PAGE_SIZE));
                        break;
                    default: return;
                }
                while (CollectionUtils.isNotEmpty(logs)) {
                    List<Transaction> transactions = new ArrayList<>(logs.size());
                    List<Long> transactionIds = new ArrayList<>(logs.size());
                    for (TransactionSendLog log : logs) {
                        //TODO ignore coupon's order/orderReturn and add log's id into  transactionIds
                        Order order = null ;
                        if(TransactionSendLog.Type.REFUND.equals(log.getType())){
                            OrderReturn source = orderReturnRepository.findOne(log.getOrderId());
                            // 找到原单
                            order = source.getRelatedOrder();
                        }else {
                            order = orderRepository.findOne(log.getOrderId());
                        }
                        //优惠券订单不传sap
                        if(OrderType.CASH_BY_COUPON.equalsIgnoreCase(order.getOrderType())){
                            transactionIds.add(log.getId());
                            continue;
                        }

                        try {
                            Transaction transaction = getTransaction(log);
                            transactions.add(transaction);
                            transactionIds.add(log.getId());
                        } catch (Exception e) {
                            if (!errorList.contains(log)) {
                                errorList.add(log);
                                log.setRemark(e.getMessage());
                                transactionSendLogRepository.save(log);
                            }
                            logger.error(log.getId() + "生成Transaction失败" , e);
                            continue;
                        }
                    }
                    int retryCount = 0;
                    boolean occursException = false;
                    do {
                        try {
                            retryCount++;
                            logger.info("第{}次发送小票...", retryCount);
                            TransactionService transactionService = (TransactionService) AopContext.currentProxy();
                            transactionService.doUploadTransaction(transactions, transactionIds, uploader);
                            occursException = false;
                            logger.info("第{}次发送小票成功", retryCount);
                        } catch (Exception e) {
                            occursException = true;
                            logger.warn("第{}次发送小票失败", retryCount);
                            logger.error(e.getMessage(), e);
                            try {
                                Thread.sleep(1000);
                            } catch (Exception ex) {
                                //Do nothing
                            }
                        }
                    } while (retryCount < 3 && occursException);
                    if(!occursException){
                        //获取全部未发送的日志
                        switch (uploader.getParam()){
                            case "richBaseReceipt":
                                logs = transactionSendLogRepository.findByRichBaseReceipt(false, new PageRequest(0, PAGE_SIZE+errorList.size()));
                                break;
                            case "sapReceipt":
                                logs = transactionSendLogRepository.findBySuccess(false, new PageRequest(0, PAGE_SIZE+errorList.size()));
                                break;
                            default: return;
                        }
                        //去掉已经发生错误的防止死循环
                        logs.removeAll(errorList);
                    }
                }
            }else{
                logger.warn("未获取到锁");
            }
        }catch (Exception e){
            logger.error(e.getMessage(), e);
        }finally {
            if (lock.isLocked()&&lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void doUploadTransaction(List<Transaction> transactions, List<Long> transactionIds, ReceiptSendTask.Uploader uploader) {
        try {
            if (CollectionUtils.isNotEmpty(transactionIds)) {
                int updated = 0;
                switch (uploader.getParam()){
                    case "richBaseReceipt":
                        updated = transactionSendLogRepository.setTransactionRichBaseSuccess(transactionIds);
                        break;
                    case "sapReceipt":
                        updated = transactionSendLogRepository.setTransactionSuccess(transactionIds);
                        break;
                    default: return;
                }
                if (updated == transactionIds.size()) {
                    if(CollectionUtils.isNotEmpty(transactions)){
                        boolean result = uploader.upload(XmlUtils.toXmlWithPerfixAndSuffix(transactions, Transaction.NAME_SPACE_PREFIX, Transaction.NAME_SPACE_SUFFIX));
                        if (!result) {
                            throw new RuntimeException("上传文件失败");
                        }
                    }
                } else {
                    throw new RuntimeException("更新状态失败");
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }
    /*private String toXml(List<Transaction> transactions) {
        XStream xstream = XStreamInitializer.getInstance();
        StringBuilder stringBuilder = new StringBuilder();
        if (CollectionUtils.isNotEmpty(transactions)) {
            for (Transaction transaction : transactions) {
                // 识别obj类中的注解
                xstream.processAnnotations(transaction.getClass());
                // 以压缩的方式输出XML
                StringWriter sw = new StringWriter();
                xstream.marshal(transaction, new CompactWriter(sw));
                stringBuilder.append(sw.toString());
            }
        }
        return stringBuilder.toString();

    }
    private String toXmlWithPerfixAndSuffix(List<Transaction> transactions, String perfix, String suffix) {
        String xml = toXml(transactions);
        return org.apache.commons.lang3.StringUtils.join(perfix, xml, suffix);
    }*/

    @Override
    public void sendFinanceReport(ReportSendTask.Uploader uploader) {
        RLock lock = redisson.getLock(TransactionSendLog.LOCK_KEY.concat(uploader.getParam()));
        try{
            boolean locked =  lock.tryLock(LOCKED_TIME,TimeUnit.SECONDS);
            if(locked){
                List<TransactionSendLog> errorList = new ArrayList<>();
                LocalDateTime now = LocalDateTime.now();
                int day = now.getDayOfMonth();
                LocalDate deadLine = LocalDate.of(now.getYear(), now.getMonth(), 26);
                List<TransactionSendLog> logs = null;
                if (day <= 25) {
                    logs = transactionSendLogRepository.findByCreateDateBeforeAndReportSendSuccessAndSuccessIsTrue(LocalDateUtils.fromLocalDateTime(now), Boolean.FALSE);
                } else {
                    logs = transactionSendLogRepository.findByCreateDateBeforeAndReportSendSuccessAndSuccessIsTrue(LocalDateUtils.fromLocalDate(deadLine), Boolean.FALSE);
                }
                List<ReportHeader> reports = new ArrayList<>(logs.size());
                List<Long> reportsIds = new ArrayList<>(logs.size());
                while (CollectionUtils.isNotEmpty(logs)) {
                    for (TransactionSendLog log : logs) {
                        try {
                            ReportHeader reportHeader = getReportHeader(log);
                            reports.add(reportHeader);
                            reportsIds.add(log.getId());
                        } catch (Exception e) {
                            errorList.add(log);
                            logger.warn("对log:{},获取report或者,失败原因为：{}", log.getId(), e.getMessage());
                        }
                    }
                    if (CollectionUtils.isNotEmpty(reports)) {
                        int retryCount = 0;
                        boolean occursException = false;
                        do {
                            try {
                                retryCount++;
                                logger.info("第{}次发送资金报表...", retryCount);
                                TransactionService transactionService = (TransactionService) AopContext.currentProxy();
                                transactionService.doUploadReports(reports, reportsIds, uploader);
                                occursException = false;
                                logger.info("第{}次发送资金报表成功", retryCount);
                            } catch (Exception e) {
                                occursException = true;
                                logger.warn("第{}次发送资金报表失败", retryCount);
                                logger.error(e.getMessage(), e);
                                try {
                                    Thread.sleep(1000);
                                } catch (Exception ex) {
                                    //Do nothing
                                }
                            }
                        } while (retryCount < 3 && occursException);
                        if(!occursException){
                            if (day <= 25) {
                                logs = transactionSendLogRepository.findByCreateDateBeforeAndReportSendSuccessAndSuccessIsTrue(LocalDateUtils.fromLocalDateTime(now), Boolean.FALSE);
                            } else {
                                logs = transactionSendLogRepository.findByCreateDateBeforeAndReportSendSuccessAndSuccessIsTrue(LocalDateUtils.fromLocalDate(deadLine), Boolean.FALSE);
                            }//去掉已经发生错误的防止死循环
                            logs.removeAll(errorList);
                        }
                    }
                }
            }else{
                logger.warn("未获取到锁");
            }
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }finally {
            if (lock.isLocked()&&lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void doUploadReports(List<ReportHeader> reports, List<Long> reportsIds, BaseSendTask.Uploader uploader) {
        try {
            int updated = transactionSendLogRepository.updateReportRalatedFild(true, new Date(), reportsIds);
            if (updated == reports.size()) {
                boolean result = uploader.upload(XmlUtils.toXmlWithPerfixAndSuffix(reports, ReportHeader.NAME_SPACE_PREFIX, ReportHeader.NAME_SPACE_SUFFIX));
                if (!result) {
                    throw new RuntimeException("上传文件失败");
                }
            } else {
                throw new RuntimeException("更新TransactionSendLog状态出错");
            }
        }catch (Exception e){
            logger.error(e.getMessage());
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<TransactionVO> find() {
        //找出所有小票没有发送成功的数据
        List<TransactionSendLog> logs = transactionSendLogRepository.findBySuccess(false);
        if (CollectionUtils.isEmpty(logs)) {
            return Collections.emptyList();
        }

        List<TransactionVO> vos = new ArrayList<>(logs.size());

        //循环每一条log，看一个订单里面的item是否能找到柜号
        for (TransactionSendLog log : logs) {
            List<RetailItem> items  = null;
            try {
                items = getItems(log);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //对每一个item获取柜号，获取合同
            for(RetailItem retailItem : items) {
                try {
                    RetailItemExtension extension = getZZGHNExtension(retailItem, log);//获取柜号
                    getRECNNRExtension(retailItem,log,extension);//查询合同
                } catch (Exception e) {//一旦发生错误的话，将其加入结果集
                    TransactionVO vo = new TransactionVO(log,retailItem,e.getMessage());
                    vos.add(vo);
                }
            }
        }

        return vos;
    }

    @Override
    public ResultModel findSync() {
        List<TransactionSendLog> receipt = transactionSendLogRepository.findByCurrSendReceipt();
        return ResultModel.ok(receipt.size()+"");
    }

    private ReportHeader getReportHeader(TransactionSendLog log) throws SapReportException {
        ReportHeader reportHeader = null;
        if (log.getType() == TransactionSendLog.Type.REFUND) {
            OrderReturn orderReturn = orderReturnRepository.findByOrderReturnId(log.getOrderId());
            if (null == orderReturn) {
                throw new SapReportException("没有找到相应的退单：" + log.getOrderId());
            }
            reportHeader = new ReportHeader(orderReturn, log);
        } else {
            Order order = orderRepository.findByOrderId(log.getOrderId());
            if (null == order) {
                throw new SapReportException("没有找到相应的原单：" + log.getOrderId());
            }
            reportHeader = new ReportHeader(order, log);
        }

        //String xml = reportHeader.toXML().replaceAll("\n", "");
        return reportHeader;
    }

    /*private String getSendContent(TransactionSendLog log) throws SapSendException {
        Transaction transaction = new Transaction();

        Header header = new Header(log);
        List<RetailItem> items = getItems(log);
        List<Discount> discounts = getDiscounts(items);
        List<RetailItemExtension> retailItemExtensions = getItemExtensions(items, log);
        List<Loyalty> loyalties = getLoyalties(log, items);
        List<Payment> payments = getPayments(log);

        transaction.setHeader(header);
        transaction.setItems(items);
        transaction.setDiscounts(discounts);
        transaction.setRetailItemExtensions(retailItemExtensions);
        transaction.setLoyalties(loyalties);
        transaction.setPayments(payments);

        String xml = transaction.toXML().replaceAll("\n", "");
        StringBuilder stringBuilder = new StringBuilder(xml);
        stringBuilder.insert(0, Transaction.NAME_SPACE_PREFIX)
                .append(Transaction.NAME_SPACE_SUFFIX);
        return stringBuilder.toString();
    }*/

    private Transaction getTransaction(TransactionSendLog log) throws SapSendException {
        Transaction transaction = new Transaction();

        Header header = new Header(log);
        List<RetailItem> items = getItems(log);
        if(CollectionUtils.isEmpty(items)){
            throw new SapSendException("交易明细为空");
        }
        List<Discount> discounts = getDiscounts(items);
        List<RetailItemExtension> retailItemExtensions = getItemExtensions(items, log);
        if(CollectionUtils.isEmpty(retailItemExtensions)){
            throw new SapSendException("柜号、合同号为空");
        }
        List<Loyalty> loyalties = getLoyalties(log, items);
        List<Payment> payments = getPayments(log);

        transaction.setHeader(header);
        transaction.setItems(items);
        transaction.setDiscounts(discounts);
        transaction.setRetailItemExtensions(retailItemExtensions);
        transaction.setLoyalties(loyalties);
        transaction.setPayments(payments);

        return transaction;
    }

    private List<Discount> getDiscounts(List<RetailItem> items) {
        List<Discount> discounts = new ArrayList<>(items.size());
        for (RetailItem item : items) {
            Discount discount = new Discount(item.getRetailNumber());
            discounts.add(discount);
        }
        return discounts;
    }

    private List<Payment> getPayments(TransactionSendLog log) {
        List<Payment> payments = new ArrayList<>(1);
        if (log.getType() == TransactionSendLog.Type.REFUND) {
            OrderReturn orderReturn = orderReturnRepository.findByOrderReturnId(log.getOrderId());
            Payment payment = new Payment(orderReturn);
            payments.add(payment);
        } else {
            Order order = orderRepository.findByOrderId(log.getOrderId());
            Payment payment = new Payment(order);
            payments.add(payment);
        }
        return payments;
    }

    private List<Loyalty> getLoyalties(TransactionSendLog log, List<RetailItem> items) {
        List<Loyalty> loyalties = new ArrayList<>(items.size());
        Order order = null;
        if (log.getType() == TransactionSendLog.Type.REFUND) {
            //找到退单
            OrderReturn orderReturn = orderReturnRepository.findOne(log.getOrderId());
            //原单
            order = orderReturn.getRelatedOrder();
        } else {
            order = orderRepository.findByOrderId(log.getOrderId());
        }
        OrderAttribute attribute = orderAttributeRepository.findFirstByAttributeNameAndOrder(OrderAttribute.LOYALTY_NUMBER, order);
        for (RetailItem item : items) {
            Loyalty loyalty = new Loyalty(item.getRetailNumber(), attribute);
            loyalties.add(loyalty);
        }
        return loyalties;
    }

    private List<RetailItemExtension> getItemExtensions(List<RetailItem> items, TransactionSendLog log) throws SapSendException {
        List<RetailItemExtension> result = new ArrayList<>();
        for (RetailItem item : items) {
            RetailItemExtension ZZGHNExtension = getZZGHNExtension(item, log);
            RetailItemExtension RECNNRExtension = getRECNNRExtension(item, log, ZZGHNExtension);
            RetailItemExtension CONSPROCGExtension = getCONSPROCGExtension(item, log);
            RetailItemExtension defaultExtension = getDefaultExtension(item);

            result.add(ZZGHNExtension);
            result.add(RECNNRExtension);
            result.add(CONSPROCGExtension);
            result.add(defaultExtension);
        }
        return result;
    }

    private RetailItemExtension getDefaultExtension(RetailItem item) {
        RetailItemExtension extension = new RetailItemExtension(item.getRetailNumber());
        return extension;
    }


    public RetailItemExtension getCONSPROCGExtension(RetailItem item, TransactionSendLog log) throws SapSendException {
        String externalId = item.getItemId();
        SapStoreGoods storeGoods = getStoreGoods(externalId, log.getStroeCode());
        if(storeGoods==null){
            storeGoods = getSapStoreProduct(externalId, log.getStroeCode());
        }
        if (null == storeGoods) {
            throw new SapSendException("没有查询到相应的寄售数据");
        }
        RetailItemExtension extension = new RetailItemExtension(item.getRetailNumber(), storeGoods);
        return extension;
    }

    public SapStoreGoods getSapStoreProduct(String externalId, String storeCode) {

        SapStoreGoods sapStoreGoods=null;
        SapStoreProduct sapStoreProduct = sapStoreProductRepository.findFirstByMatnrAndLocnr(externalId, storeCode);
        if(sapStoreProduct==null){
            sapStoreProduct = sapStoreProductRepository.findFirstByMatnr(externalId);
        }
        if(sapStoreProduct!=null){
            BeanUtils.copyProperties(sapStoreProduct,sapStoreGoods = new SapStoreGoods());
        }
        return sapStoreGoods;
    }

    @Cacheable(value = "CONSPROCGExtension", key = "#externalId + #storeCode")
    public SapStoreGoods getStoreGoods(String externalId, String storeCode) {
        SapStoreGoods storeGoods = sapStoreGoodsRepository.findFirstByMatnrAndLocnr(externalId, storeCode);
        //storeGoods若为空则直接查询商品不带门店条件，因为同一商品相关寄售控制一样
        if(storeGoods==null){
            storeGoods = sapStoreGoodsRepository.findFirstByMatnr(externalId);
        }
        return storeGoods;
    }

    private RetailItemExtension getZZGHNExtension(RetailItem item, TransactionSendLog log) throws SapSendException {
        String externalId = item.getItemId();
        List<SapContractProduct> sapContractProducts = sapContractProductRepository.
                findAllByMatnrAndWerksAndDelbsIsNull(externalId, log.getStroeCode());
        if(sapContractProducts.isEmpty()){
            throw new SapSendException("没有查询到相应的柜号:"+externalId);
        }
        // 取最后创建的柜号
        sapContractProducts.sort((o1, o2) -> o2.getNoid().compareTo(o1.getNoid()));
        SapContractProduct sapContractProduct = sapContractProducts.get(0);
        if (null == sapContractProduct) {
            throw new SapSendException("没有查询到相应的柜号:"+externalId);
        }
        SapStoreGoods storeGoods= getStoreGoods(externalId,log.getStroeCode());
       if (null == storeGoods) {
            storeGoods = getSapStoreProduct(externalId, log.getStroeCode());
        }
        if (null == storeGoods) {
            throw new SapSendException("没有查询到相应的寄售数据:"+externalId);
        }
        RetailItemExtension extension = new RetailItemExtension(item.getRetailNumber(), sapContractProduct);
        return extension;
    }

    private RetailItemExtension getRECNNRExtension(RetailItem item, TransactionSendLog log,
                                                   RetailItemExtension ZZGHNExtension) throws SapSendException {
        String ZZGHN = ZZGHNExtension.getFieldValue();
        String storeCode = log.getStroeCode();
        String formatDate = DateTimeUtil.dateToStr(log.getCreateDate(), RetailItemExtension.RECNNR_DATE_FOTMAT);

        List<SapContract> sapContracts = sapContractRepository.findAllByZzzzghnAndBenocn(ZZGHN, storeCode, formatDate);
        if (CollectionUtils.isEmpty(sapContracts) ) {
            throw new SapSendException("没有查询到相应的合同:"+item.getItemId());
        }
        SapContract sapContract = null;
        if(sapContracts.size()>1){
            sapContract = sapContracts.stream().filter(contract -> {
              return   contract!=null&&contract.getZzcontStatus()!=null&&("续签".equals(contract.getZzcontStatus())||"生效".equals(contract.getZzcontStatus()));
            }).findFirst().orElse(null);
        }else {
            sapContract = sapContracts.get(0);
        }
        if(sapContract==null){
            throw new SapSendException("没有查询到相应的合同:"+item.getItemId());
        }
        return new RetailItemExtension(item.getRetailNumber(), sapContract);
    }

    private List<RetailItem> getItems(TransactionSendLog log) throws SapSendException {
        List<RetailItem> result = new ArrayList<>();
        int retailNumber = 1;
        if (log.getType() == TransactionSendLog.Type.REFUND) {
            //从退单表里面查询数据
            List<OrderReturnItem> returnItems = orderReturnItemRepository.findByOrderReturn(new OrderReturn(log.getOrderId()));
            if (CollectionUtils.isEmpty(returnItems)) {
                throw new SapSendException("不存在的退单：" + log.getOrderId());
            }

            sortItems(returnItems);

            for (OrderReturnItem item : returnItems) {
                String externalId = item.getExternalId();
                String storeCode = log.getStroeCode();
                SapStoreGoods storeGoods = getStoreGoods(externalId, storeCode);
                if(storeGoods==null){
                    storeGoods = getSapStoreProduct(externalId,storeCode);
                }
                if(storeGoods!=null){
                    RetailItem retailItem = new RetailItem(item, storeGoods, retailNumber++, log.getType());
                    result.add(retailItem);
                }else{
                    throw new SapSendException("找不到商品与门店相关数据：" +externalId);
                }
            }
        } else {
            //从订单表查询数据
            List<OrderItem> orderItems = orderItemRepository.findByOrder(new Order(log.getOrderId()));
            if (CollectionUtils.isEmpty(orderItems)) {
                throw new SapSendException("不存在的订单：" + log.getOrderId());
            }

            sortItems(orderItems);

            for (OrderItem item : orderItems) {
                String externalId = item.getExternalId();
                SapStoreGoods storeGoods = getStoreGoods(externalId, log.getStroeCode());
                if(storeGoods==null){
                    //sapStoreProduct若为空则直接查询商品不带门店条件，因为同一商品相关寄售控制一样
                    storeGoods = getSapStoreProduct(externalId,log.getStroeCode());
                }
                if(storeGoods!=null){
                    RetailItem retailItem = new RetailItem(item, storeGoods, retailNumber++, log.getType());
                    result.add(retailItem);
                }else{
                    throw new SapSendException("找不到商品与门店相关数据：" +externalId);
                }
            }
        }
        return result;
    }

    private void sortItems(List items) throws IllegalArgumentException {
        if (items.get(0) instanceof OrderReturnItem) {
            List<OrderReturnItem> returnItems = items;
            Collections.sort(returnItems, new Comparator<OrderReturnItem>() {
                @Override
                public int compare(OrderReturnItem o1, OrderReturnItem o2) {
                    return new Long(o1.getId() - o2.getId()).intValue();
                }
            });
            return;
        } else if (items.get(0) instanceof OrderItem) {
            List<OrderItem> orderItems = items;
            Collections.sort(orderItems, new Comparator<OrderItem>() {
                @Override
                public int compare(OrderItem o1, OrderItem o2) {
                    return new Long(o1.getOrderItemId() - o2.getOrderItemId()).intValue();
                }
            });
            return;
        }
        throw new IllegalArgumentException("参数类型错误，期望的类型是List<OrderItem>或者 List<OrderReturnItem>");
    }
}
